# -*- coding: utf-8 -*-
import json
from datetime import timedelta, datetime

from sqlalchemy import func

from common.stats import MG_BIGBANG_COLL as mg
from common.stats.helper import parse_query_dct
from common.utils.decorator import mongo_wrapper
from common.utils.exceptions import ParamError
from common.utils.tz import get_utc_date


def join_field_byID(items_1, items_2 , field_arr):
    for item_1 in items_1:
        for item_2 in items_2:
            if item_1['_id'] == item_2['_id']:
                for field in field_arr:
                    item_1[field] = item_2.get('field',0)
                #items_2.remove(item_2)
    return items_1


def get_date_range(query_dct, is_key=False):
    # date_range 使用逗号分割
    # 如果是key的话，无需转换时区， 返回字符串数组
    # 否则，返回转换时区后的datetime数组
    date_range = query_dct.get('date_range', '')
    if not date_range:
        raise ParamError('date_range missed')
    date_range = date_range.split(',')
    if is_key:
        today = get_utc_date().strftime('%Y-%m-%d')
        if len(date_range) == 1:
            date_range.append(today)
        return date_range

    # 用于updated_at等具体时间的搜索
    now = datetime.utcnow()
    date_range[0] = get_utc_date(date_range[0])
    if len(date_range) == 1:
        date_range.append(now)
    else:
        date_range[1] = get_utc_date(date_range[1])
    if date_range[0] > now:
        raise ParamError['future is not coming']
    if date_range[0] > date_range[1] or date_range[1] > now:
        date_range[1] = now
    date_range[1] += timedelta(days=1)
    return date_range


def convert_filter(f):
    if f.startswith('{') or f.startswith('['):
        f = json.loads(f)
    return f


@mongo_wrapper
def get_shipping_report(date_range):
    items = mg.shipping_report.find({'_id': {'$gte': date_range[0],
                                             '$lte': date_range[1]}})
    resp_items = []
    info = {}
    for item in items:
        for k, v in item.iteritems():
            if k == '_id':
                continue
            info.setdefault(k, {}).setdefault('count', 0)
            info[k].setdefault('amount', 0)
            info[k]['count'] += v['count']
            info[k]['amount'] += v['amount']
        resp_items.append(item)

    return {'list': resp_items, 'info': info}


@mongo_wrapper
def calc_activity_total_report(query_dct):
    date_range = get_date_range(query_dct, is_key=True)
    query_dct = parse_query_dct(query_dct)
    query_dct['day'] = {'$gte': date_range[0], '$lte': date_range[1]}
    match = {}
    if len(query_dct) > 1:
        t = match['$and'] = []
        for q, v in query_dct.iteritems():
            t.append({q: v})
    else:
        match = query_dct

    items = mg.daily_acs.aggregate([
        {'$match': match},
        {'$group': {
            '_id': '$template_id',
            'name': {'$first': '$name'},
            'category_id': {'$last': '$category_id'},
            'goods_category': {'$last': '$goods_category'},
            'price': {'$last': '$price'},
            'target_amount': {'$last': '$target_amount'},
            'real_payer_count': {func: '$real_payer_count'},
            'virtual_payer_count': {func: '$virtual_payer_count'},
            'real_pay_amount': {func: '$real_pay_amount'},
            'virtual_pay_amount': {func: '$virtual_pay_amount'},
            'new_payer_count': {func: '$new_payer_count'},
            'new_pay_amount': {func: '$new_pay_amount'},
            'real_win_count': {func: '$real_win_count'},
            'virtual_win_count': {func: '$virtual_win_count'},
            'new_win_count': {func: '$new_win_count'}
        }},
        {'$sort': {'price': -1}}
    ])
    resp_items = []
    for item in items:
        resp_items.append(item)

    return {'list': resp_items}


@mongo_wrapper
def calc_activity_daily_report(query_dct):
    mode = query_dct.pop('mode', '0')  # 0: sum, 1: avg, 2:daily(plain)
    mode = int(mode)
    date_range = get_date_range(query_dct, is_key=True)
    category = query_dct.pop('category', '')
    f = {'_id': {'$gte': date_range[0], '$lte': date_range[1]}}
    resp_items = []
    if mode == 2:
        items = mg.activity_report.find(f)
        for item in items:
            if category:  # 某个类型每日数据
                dist = item.pop('dist', [])
                data = {x['_id']: x for x in dist}
                chosen = data.get(category, {})
                chosen['day'] = item['_id']
                chosen['profit_rate'] = round(float(
                    chosen['real_pay_amount'] - chosen['real_win_amount']) /
                                              chosen['real_pay_amount'], 4) if chosen.get(
                    'real_pay_amount') else 0
                resp_items.append(chosen)
            else:  # 总的每日数据
                item.pop('dist', None)
                resp_items.append(item)
    else:
        func = '$sum' if mode == 0 else '$avg'
        group = {'_id': '$dist._id'}
        for k in ('real_payer_count', 'real_pay_amount', 'virtual_win_count',
                  'real_win_count', 'real_win_amount', 'real_win_target'):
            group[k] = {func: '$dist.%s' % k}
        items = mg.activity_report.aggregate([
            {'$match': f},
            {'$unwind': '$dist'},
            {'$group': group}
        ])
        for t in items:
            t['profit_rate'] = round(float(
                t['real_pay_amount'] - t['real_win_amount']) / t[
                                         'real_pay_amount'], 4) if t.get('real_pay_amount') else 0
            resp_items.append(t)

    return {'list': resp_items}
